/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.muni.fi.pb138.gscholarinfo;

import cz.muni.fi.pb138.gscholarinfo.classes.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

/**
 *
 * @author Andrejka
 */
public class AuthorGraph {
   
    //zmena navratovej hodnoty na string (Vlado)
    public static String createGraph(AuthorPublications aps) throws IOException {
        //1. najdi mena vsetkych spoluautorov daneho autora (=zo vsetkych publikacii)
        HashMap<String,Integer> coauthors = getCoAuthors(aps);
        
        //2. zobraz (n+1)-uholnik (=n spoluautorov a autor)
        PrintWriter out = null;
        
        // Zmena - netraba pisat do suboru, staci vratit string - z prudu ByteArrayOutputStream (Vlado)
        //try {
            //out = new PrintWriter(new FileWriter("C:\\Users\\Andrejka\\DOCUMENTS\\fi_muni\\8_semester\\moderni znackovaci jazyky\\GScholarInfo\\src\\java\\cz\\muni\\fi\\pb138\\gscholarinfo\\graph.svg"));
            ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
            out = new PrintWriter(bytestream);
        /*} catch (IOException e) {
            System.err.println(e.toString());
        }*/
        
        int R = 250; //polomer kruznice opisanej danemu (n+1)-uholniku
        
        out.println("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
        out.println("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">");
        out.println("<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" width=\"" + (2*R + 175) + "\" height=\"" + (2*R + 50) + "\" viewBox=\"0 0 " + (2*R + 175) + " " + (2*R + 50) + "\">");
        
        if (coauthors.isEmpty()) {
            out.println("<text x=\"1\" y=\"20\" fill=\"black\">(No co-authors for this author.)</text>");
            out.println("</svg>");
            
            ////Zmena - vratenie stringu s danym SVG
            //out.close();
            //return;
            out.flush();
            String result = bytestream.toString();
            return result;
        }
        
        int n = coauthors.size() + 1;
        Object[] coauthNames = coauthors.keySet().toArray();
        for (int i = 0; i < n; i++) {
            float x = R*(float)Math.cos(2*Math.PI*i/n) + R + 25;
            float y = R*(float)Math.sin(2*Math.PI*i/n) + R + 10;
            out.println("<circle cx=\"" + x + "\" cy=\"" + y + "\" r=\"5\" fill=\"white\" stroke=\"black\" stroke-width=\"1\" />");
            
            if (i != n-1) {
                out.println("<text x=\"" + x + "\" y=\"" + (y+15) + "\" fill=\"black\" text-anchor=\"middle\" font-size=\"8\" >" + coauthNames[i].toString() + "</text>");
                int number = coauthors.get(coauthNames[i].toString());
                out.println("<line x1=\"" + x + "\" y1=\"" + y + "\" x2=\"" + (R*(float)Math.cos(2*Math.PI*(n-1)/n) + R + 25) + "\" y2=\"" + (R*(float)Math.sin(2*Math.PI*(n-1)/n) + R + 10) + "\" style=\"stroke:rgb" + getColour(number) + ";stroke-width:1\"/>");
            } else {
                out.println("<text x=\"" + x + "\" y=\"" + (y+15) + "\" fill=\"black\" text-anchor=\"middle\" font-size=\"8\" >" + aps.getAuthor().getName() + "</text>");
            }
        }
        
        //try {
            //najdi vsetkych coauthorov tohto coauthora (ale len spomedzi uz zakreslenych!), nakresli ciarky
            int j = 0;
            for (String ca : coauthors.keySet()) {
                List<Author> authors = new ArrayList<Author>();
                authors = GSUtils.searchAuthor(ca);
                if (authors.isEmpty()) {
                    j++;
                    continue;
                }
                HashMap<String,Integer> coauthorsOfCoauthor = getCoAuthors(GSUtils.searchAuthorPublications(authors.get(0)));
                HashSet<String> toRemove = new HashSet<String>();
                for (String c : coauthorsOfCoauthor.keySet()) {
                    if (! coauthors.containsKey(c)) {
                        toRemove.add(c);
                    }
                }
                
                int strokewidth = toRemove.size();
                
                for (String r : toRemove) {
                    coauthorsOfCoauthor.remove(r);
                }
                
                for (int i = 0; i < n-1; i++) {
                    if (coauthorsOfCoauthor.containsKey(coauthNames[i].toString())) {
                        float x = R*(float)Math.cos(2*Math.PI*i/n) + R + 25;
                        float y = R*(float)Math.sin(2*Math.PI*i/n) + R + 10;
                        int number = coauthorsOfCoauthor.get(coauthNames[i].toString());
                        out.println("<line x1=\"" + x + "\" y1=\"" + y + "\" x2=\"" + (R*(float)Math.cos(2*Math.PI*j/n) + R + 25) + "\" y2=\"" + (R*(float)Math.sin(2*Math.PI*j/n) + R + 10) + "\" style=\"stroke:rgb" + getColour(number) + ";stroke-width:1\"/>");
                    }
                }
                
                //hrubka kruzku j-teho coauthora podla toho, kolko ma este spoluautorov mimo tohto grafu
                out.println("<circle cx=\"" + (R*(float)Math.cos(2*Math.PI*j/n) + R + 25) + "\" cy=\"" + (R*(float)Math.sin(2*Math.PI*j/n) + R + 10) + "\" r=\"5\" fill=\"white\" stroke=\"black\" stroke-width=\"" + getStrokeWidth(strokewidth) + "\" />");
                
                j++;
            }
            //vynimku chceme zachytavat az na urovni servletu a zobrazit hlasku priamo na stranke (Vlado)
        /*} catch (IOException e) {
            System.err.println(e.toString());
        }*/
        
        
        //a este nakreslit legendu:
        out.println("<g>");
        float rectx = 2*R+60;
        float recty = R/2+5;
        out.println("<rect x=\"" + rectx + "\" y=\"" + recty + "\" width=\"100\" height=\"250\" fill=\"white\" stroke=\"black\" ></rect>");
        float posx = rectx + 5;
        float posy = recty + 10;
        out.println("<text x=\"" + posx + "\" y=\"" + posy + "\" font-size=\"10\" fill=\"black\" >Line colour:</text>");
        posy += 10;
        out.println("<text x=\"" + posx + "\" y=\"" + posy + "\" font-size=\"8\" fill=\"black\" >(n. of publications together)</text>");
        posy += 10;
        for (int i = 1; i <= 7; i++) {
            out.print("<text x=\"" + posx + "\" y=\"" + posy + "\" font-size=\"10\" fill=\"black\" >" + i);
            if (i == 7) {
                out.print("+");
            }
            out.println("</text>");
            out.println("<line x1=\"" + (posx + 20) + "\" y1=\"" + (posy - 4) + "\" x2=\"" + (posx + 55) + "\" y2=\"" + (posy - 4) + "\" style=\"stroke:rgb" + getColour(i) + ";stroke-width:1\"/>");
            posy += 10;
        }
        posy += 15;
        out.println("<text x=\"" + posx + "\" y=\"" + posy + "\" font-size=\"10\" fill=\"black\" >Circle style:</text>");
        posy += 10;
        out.println("<text x=\"" + posx + "\" y=\"" + posy + "\" font-size=\"8\" fill=\"black\" >(n. of other coauthors)</text>");
        posy += 15;
        for (int i = 15; i <= 75; i += 15) {
            out.print("<text x=\"" + posx + "\" y=\"" + posy + "\" font-size=\"10\" fill=\"black\" >&lt;=" + i + "</text>");
            out.println("<circle cx=\"" + (posx + 40) + "\" cy=\"" + (posy - 4) + "\" r=\"5\" fill=\"white\" stroke=\"black\" stroke-width=\"" + getStrokeWidth(i) + "\" />");
            posy += 20;
        }
        out.print("<text x=\"" + posx + "\" y=\"" + posy + "\" font-size=\"10\" fill=\"black\" >&gt; 75 </text>");
        out.println("<circle cx=\"" + (posx + 40) + "\" cy=\"" + (posy - 4) + "\" r=\"5\" fill=\"white\" stroke=\"black\" stroke-width=\"" + getStrokeWidth(90) + "\" />");
        
        
        out.println("</g>");
        
        out.println("</svg>");
        
        //Zmena - vratenie stringu s danym SVG
        //out.close();
        out.flush();
        String result = bytestream.toString();
        return result;
    }
    
    private static HashMap<String,Integer> getCoAuthors(AuthorPublications aps) {
        ArrayList<String> coauthors = new ArrayList<String>();
        for (Publication p : aps.getPublications()) {
            coauthors.addAll(p.getAuthors());
        }
        
        String author = aps.getAuthor().getName();
        String surname = aps.getAuthor().getName().split(" ")[1];
        
        HashMap<String,Integer> coauth = new HashMap<String,Integer>();
        
        ArrayList<String> toRemove = new ArrayList<String>();
        
        for (String c : coauthors) {
            if ((c.contains(surname)) && (c.charAt(0) == author.charAt(0))) { //je to (na 95%) ten dany autor
                toRemove.add(c);
            } else {
                if (coauth.containsKey(c)) {
                    coauth.put(c, coauth.get(c) + 1);
                } else {
                    coauth.put(c, 1);
                }
            }
        }
        
        coauthors.removeAll(toRemove);
        
        return coauth; //pre kazdeho spoluautora je tam pocet spoluprac s nasim autorom
    }
    
    private static String getColour(int number) {
        String colour = "";
        if (number == 1) {
            colour = "(0,0,0)";
        } else {
            if (number == 2) {
                colour = "(140,0,140)";
            } else {
                if (number == 3) {
                    colour = "(0,0,255)";
                } else {
                    if (number == 4) {
                        colour = "(0,255,0)";
                    } else {
                        if (number == 5) {
                            colour = "(255,255,0)";
                        } else {
                            if (number == 6) {
                                colour = "(255,165,0)";
                            } else {
                                colour = "(255,0,0)";
                            }
                        }
                    }
                }
            }
        }
        return colour;
    }

    private static String getStrokeWidth(int number) {
        String strokewidth = "";
        if (number <= 15) {
            strokewidth = "1";
        } else {
            if (number <= 30) {
                strokewidth = "2";
            } else {
                if (number <= 45) {
                    strokewidth = "3";
                } else {
                    if (number <= 60) {
                        strokewidth = "4";
                    } else {
                        if (number <= 75) {
                            strokewidth = "5";
                        } else {
                            strokewidth = "6";
                        }
                    }
                }
            }
        }
        return strokewidth;
    }
    
}
